﻿using System;
using System.Drawing;
using System.Drawing.Imaging;
using System.Drawing.Printing;
using System.IO;
using System.Web.Services.Protocols;
using System.Runtime.InteropServices;
using DGTestApp.localhost;
using System.Collections.Generic;
using System.Collections.ObjectModel; // For Marshal.Copy 

namespace PrintReport
{
    public class PrintReport
    {
        ReportingService rs;
        private int m_currentPageIndex;
        private List<Stream> m_streams = new List<Stream>();

        public ReadOnlyCollection<Stream> Streams
        {
            get
            {
                return m_streams.AsReadOnly();
            }
        }

        public PrintReport()
        {
            // Create proxy object and authenticate 
            rs = new ReportingService();
            rs.Credentials = System.Net.CredentialCache.DefaultCredentials;
        }

        public void RenderReport(string reportPath)
        {
            // Private variables for rendering 
            string deviceInfo = null;
            string format = "IMAGE";
            string encoding;
            string mimeType;
            Warning[] warnings = null;
            ParameterValue[] reportHistoryParameters = null;
            string[] streamIDs = null;
            m_streams = new List<Stream>();

            // Build device info based on the start page 
            deviceInfo = string.Format(@"<DeviceInfo><OutputFormat>{0}</OutputFormat></DeviceInfo>", "emf");

            //Exectute the report and get page count. 
            try
            {
                // Renders the first page of the report and returns streamIDs for 
                // subsequent pages 
                m_streams.Add(
                    new MemoryStream(rs.Render(
                reportPath,
                format,
                null,
                deviceInfo,
                null,
                null,
                null,
                out encoding,
                out mimeType,
                out reportHistoryParameters,
                out warnings,
                out streamIDs))
                );

                // The total number of pages of the report is 1 + the streamIDs 
                int numberOfPages = streamIDs.Length + 1;

                m_streams[0].Position = 0;

                for (int pageIndex = 1; pageIndex < numberOfPages; pageIndex++)
                {
                    // Build device info based on start page 
                    deviceInfo =
                    String.Format(@"<DeviceInfo><OutputFormat>{0}</OutputFormat><StartPage>{1}</StartPage></DeviceInfo>",
                    "emf", pageIndex + 1);

                    m_streams.Add(
                    new MemoryStream(rs.Render(
                    reportPath,
                    format,
                    null,
                    deviceInfo,
                    null,
                    null,
                    null,
                    out encoding,
                    out mimeType,
                    out reportHistoryParameters,
                    out warnings,
                    out streamIDs))
                    );
                }
            }

            catch (SoapException ex)
            {
                Console.WriteLine(ex.Detail.InnerXml);
            }

            catch (Exception ex)
            {
                Console.WriteLine(ex.Message);
            }

            finally
            {
                Console.WriteLine("Number of pages: {0}", m_streams.Count);
            }
        }

        public bool Print(string printerName, string reportPath)
        {
            this.RenderReport(reportPath);
            return Print(printerName);
        }

        public bool Print(string printerName)
        {
            try
            {
                // Wait for the report to completely render. 
                if (m_streams.Count < 1)
                    return false;
                PrinterSettings printerSettings = new PrinterSettings();
                printerSettings.MaximumPage = m_streams.Count;
                printerSettings.MinimumPage = 1;
                printerSettings.PrintRange = PrintRange.SomePages;
                printerSettings.FromPage = 1;
                printerSettings.ToPage = m_streams.Count;
                printerSettings.PrinterName = printerName;
                PrintDocument pd = new PrintDocument();
                m_currentPageIndex = 1;
                pd.PrinterSettings = printerSettings;

                // Print report 
                pd.PrintPage += new PrintPageEventHandler(this.pd_PrintPage);
                pd.EndPrint += new PrintEventHandler(pd_EndPrint);
                pd.Print();
                return true;
            }
            catch (Exception ex)
            {
                throw ex;
            }
        }

        private void pd_EndPrint(object sender, PrintEventArgs e)
        {
            if (m_streams != null)
            {
                foreach (Stream stream in m_streams)
                    stream.Close();
                m_streams = null;
            }
        }

        private void pd_PrintPage(object sender, PrintPageEventArgs ev)
        {
            Metafile pageImage = new Metafile(m_streams[m_currentPageIndex]);
            ev.Graphics.DrawImage(pageImage, ev.PageBounds);
            m_currentPageIndex++;
            ev.HasMorePages = (m_currentPageIndex < m_streams.Count);
        }
    }
}
